package com.zq.springcloud.rule;

import com.netflix.client.config.IClientConfig;
import com.netflix.loadbalancer.AbstractLoadBalancerRule;
import com.netflix.loadbalancer.ILoadBalancer;
import com.netflix.loadbalancer.Server;

import java.util.List;

/**
 * ================================================
 * 作    者：程志强
 * 邮    箱：cheng.zhiqiang@cesgroup.com.cn
 * 版    本：1.0.0
 * 创建日期：2021/01/05  15:03
 * 修改日期：
 * 描    述：Ribbon自定义负载均衡算法，两个类的位置不能放在SpringBoot扫描包以下，否则会我们自定义的负载均衡算法扫描，覆盖为源码默认的算法，所以退一级建立custom rule放进去
 * 修订历史：
 * ================================================
 */
public class CustomRandomRole extends AbstractLoadBalancerRule {
    // 每个服务访问5次， 然后换下一个服务
    // total=0，默认=0，如果=5，就指向下一个服务节点
    // index=0，默认=0，如果total=5， index+1

    /**
     * 被调用的次数
     */
    private int total = 0;
    /**
     * 当前提供的服务节点
     */
    private int currentIndex = 0;

    public void initWithNiwsConfig(IClientConfig iClientConfig) {

    }

    public Server choose(Object key) {
        ILoadBalancer lb = this.getLoadBalancer();
        if (lb == null) {
            return null;
        }

        Server server = null;
        while (server == null) {
            if (Thread.interrupted()) {
                return null;
            }
            // 获取活着的服务
            List<Server> servers = lb.getReachableServers();
            // 获取所有的服务
            List<Server> allServers = lb.getAllServers();
            if (allServers == null || allServers.isEmpty()) {
                return null;
            }
            // 自定义
            if (total < 5) {
                server = servers.get(currentIndex);
                total++;
            } else {
                total = 0;
                currentIndex++;
                if (currentIndex >= servers.size()) {
                    currentIndex = 0;
                }
                server = servers.get(currentIndex);
            }
            if (server != null) {
                if (server.isAlive()) {
                    return server;
                }
                server = null;
            }
            Thread.yield();
        }
        return server;
    }


}
